package com.jgp.security.shiro.component;

import com.jgp.security.component.TelCodeUtil;
import com.jgp.security.config.SecUserAdapter;
import com.jgp.security.pojo.UserInfo;
import com.jgp.security.props.SecurityConfigPropBean;
import com.jgp.security.secmodel.SecUser;
import com.jgp.security.service.SecUserService;
import com.jgp.security.shiro.AESMatcher;
import com.jgp.security.shiro.Md5Matcher;
import com.jgp.security.shiro.exception.SecurityErrorCode;
import com.jgp.security.shiro.exception.SecurityException;
import com.jgp.security.shiro.pojo.JgpUsernamePasswordToken;
import com.jgp.security.shiro.pojo.WxOpenIdToken;
import com.jgp.security.shiro.service.ShiroPowerService;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.util.Objects;

/**
 * 项目   parent
 * 作者   loufei
 * 时间   2018/4/6
 */
@Component
public class AdminAuthRealmBean extends AuthorizingRealm {
    
    @Lazy
    @Autowired
    private ShiroPowerService powerService;
    
    @Lazy
    @Autowired
    private TelCodeUtil telCodeUtil;
    
    @Lazy
    @Autowired SecUserService userService;
    
    @Lazy
    @Autowired
    private SecUserAdapter currentUserAdapter;
    
    @Lazy
    @Autowired
    private SecurityConfigPropBean configPropBean;
    
    @PostConstruct
    public void initMd5() throws IOException {
        if(configPropBean.getDbPassType().equalsIgnoreCase("md5")){
            this.setCredentialsMatcher(new Md5Matcher(configPropBean.getDevMode()));
        }else if(configPropBean.getDbPassType().equalsIgnoreCase("aes")){
            this.setCredentialsMatcher(new AESMatcher(configPropBean.getDevMode(), configPropBean.getAesKeyFile()));
        }
        
    }
    
    //认证.登录
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws
            SecurityException {
        if(token.getClass().equals(WxOpenIdToken.class)){
            WxOpenIdToken utoken = (WxOpenIdToken) token;
            String openId = utoken.getOpenId();
            SecUser user = userService.queryByThirdOpenId(openId);
            UserInfo userInfo = powerService.packageUserInfo(user,utoken.getEndPointType());
            return new SimpleAuthenticationInfo(userInfo, user.getPassword(), ByteSource.Util.bytes(user.getSugar()), this.getName());
        }else if(token.getClass().equals(JgpUsernamePasswordToken.class)){
            JgpUsernamePasswordToken utoken = (JgpUsernamePasswordToken) token;//获取用户输入的token
            String username = utoken.getUsername();
            String cacheCode = telCodeUtil.get(username);
            SecUser user = userService.queryByAccount(username);
    
            if (Objects.isNull(user)) {
                throw new SecurityException(SecurityErrorCode.AUTHENTICATION_USERNAME_NO);
            }
    
            if(StringUtils.isBlank(user.getThirdOpenId()) && StringUtils.isNotBlank(utoken.getOpenId())){
                user = userService.setThirdOpenId(user.getId(),utoken.getOpenId());
            }
    
            if (user.getLocked()) {
                throw new LockedAccountException(user.getUsername());
            }
            if(StringUtils.isNotBlank(cacheCode)){
                if(!cacheCode.equals(new String((char[])token.getCredentials()))){
                    throw new SecurityException(SecurityErrorCode.AUTHENTICATION_FAIL);
                }else {
                    user.setPassword(currentUserAdapter.encryptPwd(cacheCode,user.getSugar(),user.getEncryptTime()));
                }
            }
            SecUser superAdmin = userService.getSuperAdmin();
            String endPointType = utoken.getEndPointType();
            if(user.getUsername().equals(superAdmin.getUsername())){
                endPointType = null;
            }
            UserInfo userInfo = powerService.packageUserInfo(user,endPointType);
            return new SimpleAuthenticationInfo(userInfo, user.getPassword(), user.getSugar()==null?null:ByteSource.Util.bytes(user.getSugar()), this.getName());
        }else {
            UsernamePasswordToken utoken = (UsernamePasswordToken) token;//获取用户输入的token
            String username = utoken.getUsername();
            SecUser user = userService.queryByAccount(username);
    
            if (Objects.isNull(user)) {
                throw new SecurityException(SecurityErrorCode.AUTHENTICATION_USERNAME_NO);
            }
            
            if (user.getLocked()) {
                throw new LockedAccountException(user.getUsername());
            }
           
            UserInfo userInfo = powerService.packageUserInfo(user,null);
            return new SimpleAuthenticationInfo(userInfo, user.getPassword(), ByteSource.Util.bytes(user.getSugar()), this.getName());
        }
    }
    
    @Override
    public AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        UserInfo user = (UserInfo) principals.getPrimaryPrincipal();
        return powerService.authorizationInfo(user);
    }
    
    @Override
    protected Object getAuthorizationCacheKey(PrincipalCollection principals) {
        return super.getAuthorizationCacheKey(principals);
    }
    
    @Override
    public void setName(String name) {
        super.setName("adminRealm");
    }
}
